#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

// #define MySelf 1

const std::string blank_space = " ";
const std::string splitting_symbol = "\n";

//"len"\n"content"\n
std::string Encapsulation(const std::string &content)
{
    std::string ret = std::to_string(content.size());
    ret += splitting_symbol;
    ret += content;
    ret += splitting_symbol; // 最后的不要忘了加上
    return ret;
}

bool Decapsulation(std::string &package, std::string *content)
{
    size_t pos = package.find(splitting_symbol);
    if (pos == std::string::npos)
        return false;
    // std::cout<<"snow "<<std::endl;

    std::string str = package.substr(0, pos);
    int content_len = std::stoi(str);
    // std::cout<<content_len<<" " << package.size()<<" "<<str.size()<<std::endl;
    int total_len = str.size() + content_len + 2; // 需要多次用到，用一个变量存储起来
    if (total_len > package.size())
        return false;
    // std::cout<<"snow "<<std::endl;

    *content = package.substr(pos + 1, content_len);
    package.erase(0, total_len);
    return true;
}

class Request
{
public:
    Request(int data1, int data2, char op)
        : data1_(data1), data2_(data2), oper_(op)
    {
    }
    Request()
    {
    }

    // data1 oper data2
    bool Serialize(std::string *content)
    {
#ifdef MySelf
        std::string str = std::to_string(data1_);
        str += blank_space;

        // oper_本身就是字符，无需再转成字符串，否则下方的Deserialize函数将出错
        //  str += std::to_string(oper_);
        str += oper_;
        str += blank_space;
        str += std::to_string(data2_);
        *content = str;
#else
        Json::Value root;
        root["data1_"] = data1_;
        root["data2_"] = data2_;
        root["oper_"] = oper_;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *content = w.write(root);
#endif
        return true;
    }
    bool Deserialize(const std::string &package)
    {
#ifdef MySelf
        size_t left_pos = package.find(blank_space);
        if (left_pos == std::string::npos)
            return false;
        size_t right_pos = package.rfind(blank_space);
        if (right_pos == std::string::npos)
            return false;
        if (left_pos + 2 != right_pos)
            return false;
        data1_ = std::stoi(package.substr(0, left_pos));
        oper_ = package[left_pos + 1];
        data2_ = std::stoi(package.substr(right_pos + 1));
#else
        Json::Value root;
        Json::Reader r;
        r.parse(package, root);
        data1_ = root["data1_"].asInt();
        data2_ = root["data2_"].asInt();
        oper_ = root["oper_"].asInt();
#endif
        return true;
    }
    // private:
public:
    int data1_;
    int data2_;
    char oper_;
};

class Response
{
public:
    Response(int result, int code)
        : result_(result), code_(code)
    {
    }

    Response()
    {
    }

    // result code
    bool Serialize(std::string *content)
    {
#ifdef MySelf
        std::string str = std::to_string(result_);
        str += blank_space;
        str += std::to_string(code_);
        *content = str;
#else
        Json::Value root;
        root["result_"] = result_;
        root["code_"] = code_;
        // Json::FastWriter w;
        Json::StyledWriter w;
        *content = w.write(root);
#endif
        return true;
    }
    bool Deserialize(const std::string &package)
    {
#ifdef MySelf
        size_t pos = package.find(blank_space);
        if (pos == std::string::npos)
            return false;
        result_ = std::stoi(package.substr(0, pos));
        code_ = std::stoi(package.substr(pos + 1));
#else
        Json::Value root;
        Json::Reader r;
        r.parse(package, root);
        result_ = root["result_"].asInt();
        code_ = root["code_"].asInt();
#endif
        return true;
    }

    // private:
public:
    int result_;
    int code_;
};